#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
const int N = 20, M = 1 << N;
int f[M][N]; //用第一个参数的二进制位来表示是否走过某个点。第二个参数表示终点
int w[N][N];
int n;
int main()
{
    cin >> n;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            scanf("%d", &w[i][j]);
        }
    }
    memset(f, 0x3f, sizeof(f));
    f[1][0] = 0;
    for (int i = 0; i < 1 << n; i++) //所有点的情况
    {
        for (int j = 0; j < n; ++j) //寻找最短
        {
            if ((i >> j) & 1) //判断j这个位置是否走过
            {
                for (int k = 0; k < n; ++k)
                {
                    if ((i >> k) & 1) 
                    {
                        f[i][j] = min(f[i][j], f[i - (1 << j)][k] + w[k][j]); //求从已走过的点中，走到j的最小值;
                    }
                }
            }
        }
    }
    cout << f[(1 << n) - 1][n - 1];
    return 0;
}